package com.ioidea.base.mvvm

import androidx.lifecycle.DefaultLifecycleObserver
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import com.ioidea.base.ui.mvvm.IUiEvent
import com.ioidea.base.ui.mvvm.loading.BaseUIState
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.Job
import kotlinx.coroutines.flow.MutableSharedFlow
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.asSharedFlow
import kotlinx.coroutines.flow.asStateFlow
import kotlinx.coroutines.launch
import kotlin.coroutines.CoroutineContext
import kotlin.coroutines.EmptyCoroutineContext


/**
 * 说明：在子类实现时 在init里面调用initUIState()方法初始化_uiState
 * 不然报 lateinit property _uiState has not been initialized
 */
abstract class MvvmBaseViewModel<Event : IUiEvent, State : BaseUIState> : ViewModel(),
    DefaultLifecycleObserver {


    // 初始化视图状态
    private val initialState: State by lazy { createInitialState() }
    abstract fun createInitialState(): State

    /**
     * 特定的用户操作,如：按钮点击，登录，激活等
     */
    private val _event: MutableSharedFlow<Event> = MutableSharedFlow()
    val event = _event.asSharedFlow()


    /**
     * 当前的视图状态
     */
    private val _uiState: MutableStateFlow<State> = MutableStateFlow(initialState)
    val uiState = _uiState.asStateFlow()

    /**
     * 获取当前视图状态值
     */
    protected val currentState: State
        get() = uiState.value

    init {
        subscribeToEvents()
    }

    // 当前异步任务列表
    private val asyncJobs: MutableList<Job> = mutableListOf()

    //直接使用asyncLaunch订阅asyncJobs会空 可能是init初始化的问题  暂时用一个变量
    private var subscriberToEventJob: Job? = null


    /**
     * 订阅用户操作
     */
    private fun subscribeToEvents() {
        subscriberToEventJob = viewModelScope.launch {
            _event.collect {
                handleEvents(it)
            }
        }
    }

    /**
     * 处理用户的操作
     */
    abstract fun handleEvents(event: Event)

    fun asyncLaunch(
        context: CoroutineContext = EmptyCoroutineContext,
        block: suspend CoroutineScope.() -> Unit
    ) = viewModelScope.launch(context = context) {
        block.invoke(this)
    }.apply {
//        MyLogger.hLog().e("asyncJobs.size:0")
//        MyLogger.hLog().e("将任务添加到 asyncJobs，当前大小: ${asyncJobs.size}")
        asyncJobs.add(this)
//        MyLogger.hLog().e("任务已添加，新 asyncJobs 大小: ${asyncJobs.size}")
    }

    /**
     * 双重保险 Screen里面使用的collectAsStateWithLifecycle 应该不会泄漏到Screen里面去
     * ViewModel即将销毁的时候，取消所有正在进行的任务
     */
    override fun onCleared() {
//        MyLogger.hLog().e("清空 asyncJobs，当前大小: ${asyncJobs.size}")
        if (subscriberToEventJob != null && !subscriberToEventJob!!.isCancelled) {
            subscriberToEventJob!!.cancel()
        }
        val iterator = asyncJobs.iterator()
        while (iterator.hasNext()) {
            val job = iterator.next()
            if (!job.isCancelled) {
                job.cancel()
            }
            iterator.remove()
        }
//        MyLogger.hLog().e("所有任务已清空，asyncJobs 大小: ${asyncJobs.size}")
        super.onCleared()
    }

    /**
     * 设置当前视图状态
     */
    fun setState(reduce: State.() -> State) {
        val newState = currentState.reduce()
        _uiState.value = newState
    }


    /**
     * 特定的用户操作,如：按钮点击，收藏，删除等
     */
    fun setEvent(event: Event) {
        val newEvent = event
        asyncLaunch(Dispatchers.IO) {
            _event.emit(newEvent)
        }
    }


    protected fun showLoading() {
        _uiState.value.let {
            val updatedState = it.getLoadingMsg().copy(loading = true)
            _uiState.value = it.copyWithLoadingMsg(updatedState) as State
        }
    }

    protected fun hideLoading() {
        _uiState.value.let {
            val updatedState = it.getLoadingMsg().copy(loading = false)
            _uiState.value = it.copyWithLoadingMsg(updatedState) as State
        }
    }



}


